/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.epcs.model.dao.outlookWrapper;

import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.client.fluent.Form;

import com.epcs.model.dto.outlook.OutlookCalendar;
import com.epcs.model.dto.outlook.OutlookCalendarList;
import com.epcs.model.dto.outlook.OutlookEvent;
import com.epcs.model.dto.outlook.OutlookEventList;
import com.epcs.model.dto.outlook.OutlookToken;
import com.epcs.util.EpcsDateTimeUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 *
 * @author Hà Hải Đăng
 */
public class OutlookAPIWrapper {

    private static String clientID = "000000004C113A19";
    private static String clientSecret = "I39eLcaad42NMpajQtItY8BtDVVNYbRO";
    private String refreshToken = "";
    private String accessToken = "";
    private Gson gson;

    public OutlookAPIWrapper() {
        gson = new Gson();
    }

    public OutlookAPIWrapper(String refreshToken) {
        gson = new GsonBuilder().create();
        this.refreshToken = refreshToken;
        this.accessToken = getAccessToken(refreshToken);
    }

    public static String getAuthURL() {

        String authOutlookURL = "https://login.live.com/oauth20_authorize.srf?"
                + "&response_type=code"
                + "&scope=%s"
                + "&redirect_uri=%s"
                + "&client_id=%s";

        String outlookScope = "wl.offline_access wl.calendars wl.calendars_update";
        String redirect_uri = "http://epcs.com:8080/EPCS/ProcessPermission.do";

        String finalOutlookAuthUrl = String.format(authOutlookURL, outlookScope, redirect_uri, clientID);

        return finalOutlookAuthUrl;
    }

    public String getRefreshToken(String authorizedCode) {
        String url = "https://login.live.com/oauth20_token.srf";
        
        Form myForm = Form.form();
        myForm.add("code", authorizedCode);
        myForm.add("client_id", clientID);
        myForm.add("client_secret", clientSecret);
        myForm.add("redirect_uri", "http://epcs.com:8080/EPCS/ProcessPermission.do");
        myForm.add("grant_type", "authorization_code");
        
        List<NameValuePair> form = myForm.build();

        String result = WebUtil.postResult(url, form);

        OutlookToken token = gson.fromJson(result, OutlookToken.class);
        return token.getRefresh_token();
    }

    public final String getAccessToken(String refreshToken) {
        String url = "https://login.live.com/oauth20_token.srf";

        Form myForm = Form.form();
        myForm.add("refresh_token", refreshToken);
        myForm.add("client_id", clientID);
        myForm.add("client_secret", clientSecret);
        myForm.add("grant_type", "refresh_token");

        List<NameValuePair> form = myForm.build();

        String result = WebUtil.postResult(url, form);

        OutlookToken token = gson.fromJson(result, OutlookToken.class);
        return token.getAccess_token();
    }

    public String getAccessToken() {
        return this.accessToken;
    }

    public List<OutlookCalendar> getCalendarList() {
        String url = "https://apis.live.net/v5.0/me/calendars";
        url += "?fields=items(id,name,description)";
        String result = WebUtil.getResult(url, accessToken);
        
        OutlookCalendarList calendarList = gson.fromJson(result, OutlookCalendarList.class);

        if (calendarList != null) {
        	return calendarList.getData();
        }
        
        return null;
    }

    public List<OutlookEvent> getEventList(String calendarId) {
        String url = "https://apis.live.net/v5.0/%s/events";
        url = String.format(url, calendarId);
        String result = WebUtil.getResult(url, accessToken);

        OutlookEventList eventList = gson.fromJson(result, OutlookEventList.class);

        if (eventList != null) {
        	return eventList.getData();
        }
        
        return null;
    }
    
    /**
	 * Method chỉ thực hiện trong khoảng thời gian tối đa là 3 tháng. 
	 * EX: tháng 1 đến tháng 3. 
	 * Chưa validate trong khoảng 3 tháng. 
	 * Khuyên dùng null cho giá trị toMonth để tự động
	 * 
	 * @param calendarId
	 * @param fromMonth là tháng trong năm (EX: 1, 12)
	 * @param toMonth là tháng trong năm (EX: 1, 12)
	 * @param isCurrentYear
	 *            để xác định là load trong năm nay hay năm tiếp theo. Nếu isCurrentYear = true thì
	 *            sẽ load data trong năm hiện tại. Nếu isCurrentYear = false thì sẽ load data trong
	 *            năm (hiện tại + 1)
	 * @return
	 */
	public List<OutlookEvent> getEventList(String calendarId, String fromMonth, String toMonth, boolean isCurrentYear) {

		// method chỉ thực hiện trong năm, với khoảng thời gian trong 3 tháng
		// NOTE: Outlook ko thể tìm lớn hơn 3 tháng
		String fromDateTime = "";
		String toDateTime = "";
		int yearOfData = EpcsDateTimeUtil.getCurrentYearInteger();
		
		if (!isCurrentYear){
			yearOfData = yearOfData + 1;
		}
		
		// nếu ko có fromMonth --> mặc định là current month
		if (fromMonth == null) {
			// set lại fromMonth vì chưa có
			fromMonth = EpcsDateTimeUtil.getCurrentMothString();
			// tạo param value truyền cho start_time
			fromDateTime = (yearOfData + "-" + fromMonth + "-01T00:00:00Z");
		} else {
			// chuyển thành dạng 2 chữ số (nếu chưa là 2 chữ số)
			fromMonth = EpcsDateTimeUtil.covertTo2Digit(fromMonth);
			// tạo param value truyền cho start_time
			fromDateTime = (yearOfData + "-" + fromMonth + "-01T00:00:00Z");

		}

		// nếu ko có toMonth --> mặc định là current month + 3 tháng (lấy trong thời gian 3 tháng);
		if (toMonth == null) {
			// toMonth co thể vượt qua 12 --> sang năm mới --> kiểm tra trường hợp > 12 tháng
			// nếu lớn hơn 12 tháng thì chỉ lấy data của trong năm, trường hợp đó bên ngoài xử sau
			int tempToMonth = Integer.parseInt(fromMonth) + 3;

			if (tempToMonth > 12) {
				int nextYear = yearOfData + 1;
				// set lại toMonth tới ngày đầu năm sau yyyy-01-01
				toMonth = "01";
				// tạo param value truyền cho end_time
				toDateTime = (nextYear + "-" + toMonth + "-01T00:00:00Z");
			} else {
				// set lại toMonth = fromMonth + 3 vì chưa có
				toMonth = EpcsDateTimeUtil.covertTo2Digit(String.valueOf(Integer.parseInt(fromMonth) + 3));
				// tạo param value truyền cho end_time
				toDateTime = (yearOfData + "-"  + toMonth + "-01T00:00:00Z");
			}

		} else {
			/*
			 * Người ta hay sử dụng from và to để chỉ KHOẢNG thời gian --> Nhưng với service thì
			 * from = current --> và to = from + khoảng thời gian vậy nếu from = tháng 4 mà tìm
			 * trong khoảng 3 tháng thì to = 2 + 3 = 7 --> phải công thêm 1 đơn vị cho 'to'
			 */

			int tempToMonth = Integer.parseInt(toMonth) + 1;

			// nếu cộng lại mà toMonth lớn hơn 12 thì --> sang năm mới --> tháng quay về 01 tháng
			if (tempToMonth > 12) {
				int nextYear = yearOfData + 1;
				// set lại toMonth tới ngày đầu năm sau yyyy-01-01
				toMonth = "01";
				// tạo param value truyền cho end_time
				toDateTime = (nextYear + "-" + toMonth + "-01T00:00:00Z");
				
			} else {
				// chuyển thành dạng 2 chữ số (nếu chưa là 2 chữ số)
				toMonth = EpcsDateTimeUtil.covertTo2Digit(String.valueOf(tempToMonth));
				// tạo param value truyền cho end_time
				toDateTime = (yearOfData + "-"  + toMonth + "-01T00:00:00Z");
			}

		}


		String url = "https://apis.live.net/v5.0/%s/events?start_time=%s&end_time=%s";

		url = String.format(url, calendarId, fromDateTime, toDateTime);
		String result = WebUtil.getResult(url, accessToken);

		OutlookEventList eventList = gson.fromJson(result, OutlookEventList.class);

		if (eventList != null) {
        	return eventList.getData();
        }
        
        return null;
	}

    public OutlookCalendar insertCalendar(String calendarName, String description) {
        String url = "https://apis.live.net/v5.0/me/calendars";

        // tao mot calendar voi description
        OutlookCalendar calendar = new OutlookCalendar();
        calendar.setName(calendarName);
        calendar.setDescription(description);

        // chuyen calendar thanh Json
        gson = getExposeOnlyGson();
        String calendarGson = gson.toJson(calendar);

        //dua gson len server
        String result = WebUtil.postResult(url, accessToken, calendarGson);
        
        calendar = gson.fromJson(result, OutlookCalendar.class);
        return calendar;
    }

    public OutlookEvent insertEvent(Object eventItem) {

        String url = "https://apis.live.net/v5.0/%s/events";
        if (eventItem instanceof OutlookEvent) {
            url = String.format(url, ((OutlookEvent) eventItem).getCalendar_id());
        }

        // chuyen event thanh Json
        String eventGson = gson.toJson(eventItem);

        //dua gson len server
        String result = WebUtil.postResult(url, accessToken, eventGson);

        return gson.fromJson(result, OutlookEvent.class);
    }

    public OutlookCalendar updateCalendar(Object calendarItem) {

        String url = "https://apis.live.net/v5.0/%s";
        if (calendarItem instanceof OutlookCalendar) {
            String calendarID = ((OutlookCalendar) calendarItem).getId();
            url = String.format(url, calendarID);
        }

        // bien calendar thanh Json
        String calendarGson = gson.toJson(calendarItem);

        // chuyen gson len server
        String result = WebUtil.putResult(url, accessToken, calendarGson);

        return gson.fromJson(result, OutlookCalendar.class);

    }

    public OutlookEvent updateEvent(Object eventItem) {

        String url = "https://apis.live.net/v5.0/%s";
        if (eventItem instanceof OutlookEvent) {
            String eventID = ((OutlookEvent) eventItem).getId();
            url = String.format(url, eventID);
        }

        // chuyen event thanh Json
        String eventGson = gson.toJson(eventItem);

        //dua gson len server
        String result = WebUtil.putResult(url, accessToken, eventGson);

        return gson.fromJson(result, OutlookEvent.class);

    }

    public OutlookEvent getEvent(String eventId) {
        String url = "https://apis.live.net/v5.0/%s";
        url = String.format(url, eventId);

        String result = WebUtil.getResult(url, accessToken);
        OutlookEvent event = gson.fromJson(result, OutlookEvent.class);
        return event;
    }

    public void deleteCalendar(String calendarId) {
        String url = "https://apis.live.net/v5.0/%s";
        url = String.format(url, calendarId);

        WebUtil.deleteResult(url, accessToken);
    }

    public void deleteEvent(String eventId) {
        String url = "https://apis.live.net/v5.0/%s";
        url = String.format(url, eventId);

        WebUtil.deleteResult(url, accessToken);
    }

    private Gson getExposeOnlyGson() {
        return new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
    }

}
